import os
import sys
import hashlib
import logging
import datetime
from stat import *

#-----------------------------------------------
#Logging

def log(dstDir):
  logFile = "find_in" + dstDir.replace(os.sep,'_') + str(os.getpid()) + '.log'  
  logging.basicConfig(filename = logFile, filemode = 'a', level = logging.NOTSET, \
                      format = '%(levelname)s: %(message)s')
  return logFile

#-----------------------------------------------
#MD5

def calHash(str, hashType = 'md5'):
  m = hashlib.md5()
  if hashType == 'sha1':
    m = hashlib.sha1()
  m.update(str)
  return m.hexdigest() 
   
 
def calHashForFile(file, hashType = 'md5'):
  a_file = open(file, 'rb')
  hash = calHash(a_file.read(),hashType)
  a_file.close()
  return hash 
    
#-----------------------------------------------
#Main functions
def main(srcRoot,dupFiles): 
  items = os.listdir(srcRoot)
  for item in items:
      itemFullPath = os.path.join(srcRoot,item)
      if not os.path.exists(itemFullPath): continue
      if os.path.islink(itemFullPath): continue
      if os.path.isdir(itemFullPath): 
        main(itemFullPath,dupFiles) 
        continue

      #else the item is file
      hash = calHashForFile(itemFullPath)
      inode = os.stat(itemFullPath)[ST_INO]  
      if hash in dupFiles.keys(): 
        if inode in dupFiles[hash].keys():
       dupFiles[hash][inode].append(itemFullPath)
    else:
       dupFiles[hash][inode] = [itemFullPath]
      else:
        dupFiles[hash] = {inode:[itemFullPath]}

def printDupFiles(dupFiles):
   wasteDisk = 0
   for hash in dupFiles.keys():
     dupNum = len(dupFiles[hash])
     if dupNum <= 1: continue
     logging.info("-----------------------------")
     logging.info("hash: " + hash)
     itemSize = 0  
     for inode,items in dupFiles[hash].items():
       logging.info("inode: " + str(inode))
       if len(items) > 0 and itemSize == 0 : itemSize = os.path.getsize(items[0]) 
       for item in items:
           logging.info("  " + item)
     wasteDisk += itemSize * dupNum - itemSize
   logging.info("waste disk: " + str(wasteDisk))

#-----------------------------------------------
#Main entry

if __name__ == "__main__" :
  if len(sys.argv) < 2:  
    exit(1)
    
  srcRoot = sys.argv[1]
  
  if not os.path.exists(srcRoot) or not os.path.isdir(srcRoot): 
    logging.error(srcRoot + " is not exist or is not one directory")
    exit(1)
    
  logFileName = log(srcRoot)
  startTime = datetime.datetime.now()
  dupFiles = {}
  main(srcRoot,dupFiles)
  printDupFiles(dupFiles)
  endTime = datetime.datetime.now()
  logging.info("")
  logging.info("total time:" + str(endTime - startTime))
  exit(0)
    
    
#testing

